/*     */ package com.zimbra.cs.server;
/*     */ 
/*     */ import com.google.common.collect.ArrayListMultimap;
/*     */ import com.google.common.collect.Multimap;
/*     */ import com.google.common.util.concurrent.ThreadFactoryBuilder;
/*     */ import com.zimbra.common.localconfig.KnownKey;
/*     */ import com.zimbra.common.localconfig.LC;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.ByteUtil;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.NetUtil;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.Provisioning;
/*     */ import com.zimbra.cs.util.Zimbra;
/*     */ import java.io.FileInputStream;
/*     */ import java.io.IOException;
/*     */ import java.lang.management.ManagementFactory;
/*     */ import java.security.KeyStore;
/*     */ import java.util.HashSet;
/*     */ import java.util.Map;
/*     */ import java.util.Set;
/*     */ import java.util.concurrent.Executor;
/*     */ import java.util.concurrent.ExecutorService;
/*     */ import java.util.concurrent.Executors;
/*     */ import java.util.concurrent.ThreadPoolExecutor;
/*     */ import java.util.concurrent.TimeUnit;
/*     */ import javax.management.MBeanServer;
/*     */ import javax.management.ObjectName;
/*     */ import javax.net.ssl.KeyManagerFactory;
/*     */ import javax.net.ssl.SSLContext;
/*     */ import javax.net.ssl.SSLEngine;
/*     */ import javax.net.ssl.TrustManagerFactory;
/*     */ import org.apache.mina.core.buffer.IoBuffer;
/*     */ import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
/*     */ import org.apache.mina.core.filterchain.IoFilter;
/*     */ import org.apache.mina.core.service.IoProcessor;
/*     */ import org.apache.mina.core.service.SimpleIoProcessorPool;
/*     */ import org.apache.mina.core.session.IoEventType;
/*     */ import org.apache.mina.core.session.IoSession;
/*     */ import org.apache.mina.filter.codec.ProtocolCodecFactory;
/*     */ import org.apache.mina.filter.codec.ProtocolCodecFilter;
/*     */ import org.apache.mina.filter.codec.ProtocolEncoder;
/*     */ import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
/*     */ import org.apache.mina.filter.codec.ProtocolEncoderOutput;
/*     */ import org.apache.mina.filter.executor.ExecutorFilter;
/*     */ import org.apache.mina.filter.ssl.ZimbraSslFilter;
/*     */ import org.apache.mina.transport.socket.SocketSessionConfig;
/*     */ import org.apache.mina.transport.socket.nio.NioProcessor;
/*     */ import org.apache.mina.transport.socket.nio.NioSession;
/*     */ import org.apache.mina.transport.socket.nio.ZimbraSocketAcceptor;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public abstract class NioServer
/*     */   implements Server
/*     */ {
/*  75 */   private static final Multimap<Class<? extends NioServer>, IoFilter> FILTERS = ;
/*  76 */   protected static final ProtocolEncoder DEFAULT_ENCODER = new DefaultEncoder(null);
/*     */   
/*     */   protected final ExecutorFilter executorFilter;
/*     */   
/*     */   protected final ZimbraSocketAcceptor acceptor;
/*     */   
/*     */   protected final ServerConfig config;
/*     */   private static SSLContext sslContext;
/*     */   private static String[] mSslEnabledCipherSuites;
/*  85 */   private static final IoProcessor<NioSession> IO_PROCESSOR_POOL = new SimpleIoProcessorPool(NioProcessor.class, Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("NioProcessor-%d").build()));
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static void addFilter(Class<? extends NioServer> server, IoFilter filter)
/*     */   {
/*  96 */     FILTERS.put(server, filter);
/*     */   }
/*     */   
/*     */   private static synchronized SSLContext getSSLContext() {
/* 100 */     if (sslContext == null) {
/*     */       try {
/* 102 */         sslContext = initSSLContext();
/*     */       } catch (Exception e) {
/* 104 */         Zimbra.halt("exception initializing SSL context", e);
/*     */       }
/*     */     }
/* 107 */     return sslContext;
/*     */   }
/*     */   
/*     */   private static SSLContext initSSLContext() throws Exception {
/* 111 */     FileInputStream fis = null;
/*     */     try {
/* 113 */       KeyStore ks = KeyStore.getInstance("JKS");
/* 114 */       char[] pass = LC.mailboxd_keystore_password.value().toCharArray();
/* 115 */       fis = new FileInputStream(LC.mailboxd_keystore.value());
/* 116 */       ks.load(fis, pass);
/* 117 */       KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
/* 118 */       kmf.init(ks, pass);
/* 119 */       TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
/* 120 */       tmf.init(ks);
/* 121 */       SSLContext context = SSLContext.getInstance("TLS");
/* 122 */       context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
/* 123 */       return context;
/*     */     } finally {
/* 125 */       ByteUtil.closeStream(fis);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private static synchronized String[] getSSLEnabledCiphers(SSLContext sslCtxt, ServerConfig serverConfig)
/*     */   {
/* 157 */     if (mSslEnabledCipherSuites == null) {
/*     */       try {
/* 159 */         String[] excludeCiphers = serverConfig.getSslExcludedCiphers();
/*     */         
/* 161 */         if ((excludeCiphers != null) && (excludeCiphers.length > 0))
/*     */         {
/* 163 */           SSLEngine sslEng = sslCtxt.createSSLEngine();
/* 164 */           String[] enabledCiphers = serverConfig.getSslIncludedCiphers();
/* 165 */           if ((enabledCiphers == null) || (enabledCiphers.length == 0)) {
/* 166 */             enabledCiphers = sslEng.getEnabledCipherSuites();
/*     */           }
/* 168 */           mSslEnabledCipherSuites = NetUtil.computeEnabledCipherSuites(enabledCiphers, excludeCiphers);
/*     */         }
/*     */         
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 177 */         if (mSslEnabledCipherSuites == null) {
/* 178 */           mSslEnabledCipherSuites = new String[0];
/*     */         }
/*     */       } catch (Exception e) {
/* 181 */         Zimbra.halt("exception initializing SSL enabled ciphers", e);
/*     */       }
/*     */     }
/* 184 */     return mSslEnabledCipherSuites;
/*     */   }
/*     */   
/*     */   public ZimbraSslFilter newSSLFilter() {
/* 188 */     SSLContext sslCtxt = getSSLContext();
/* 189 */     ZimbraSslFilter sslFilter = new ZimbraSslFilter(sslCtxt);
/* 190 */     String[] sslProtocols = this.config.getMailboxdSslProtocols();
/* 191 */     if ((sslProtocols != null) && (sslProtocols.length > 0)) {
/* 192 */       sslFilter.setEnabledProtocols(sslProtocols);
/*     */     }
/* 194 */     String[] enabledCiphers = getSSLEnabledCiphers(sslCtxt, this.config);
/* 195 */     if (enabledCiphers.length > 0)
/* 196 */       sslFilter.setEnabledCipherSuites(enabledCiphers);
/* 197 */     return sslFilter;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   protected NioServer(ServerConfig config)
/*     */     throws ServiceException
/*     */   {
/* 207 */     this.config = config;
/* 208 */     this.acceptor = new ZimbraSocketAcceptor(config.getServerSocketChannel(), IO_PROCESSOR_POOL);
/* 209 */     this.executorFilter = new ExecutorFilter(1, config.getMaxThreads(), config.getThreadKeepAliveTime(), TimeUnit.SECONDS, new ThreadFactoryBuilder().setNameFormat(getName() + "-%d").build(), new IoEventType[] { IoEventType.EXCEPTION_CAUGHT, IoEventType.MESSAGE_RECEIVED, IoEventType.SESSION_CLOSED, IoEventType.SESSION_IDLE, IoEventType.SESSION_OPENED });
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public ServerConfig getConfig()
/*     */   {
/* 224 */     return this.config;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public void start()
/*     */   {
/* 235 */     ServerConfig sc = getConfig();
/* 236 */     DefaultIoFilterChainBuilder fc = this.acceptor.getFilterChain();
/* 237 */     if (sc.isSslEnabled()) {
/* 238 */       fc.addFirst("ssl", newSSLFilter());
/*     */     }
/* 240 */     fc.addLast("executer", this.executorFilter);
/* 241 */     fc.addLast("logger", new NioLoggingFilter(this, false));
/* 242 */     fc.addLast("codec", new ProtocolCodecFilter(getProtocolCodecFactory()));
/* 243 */     for (IoFilter filter : FILTERS.get(getClass())) {
/* 244 */       fc.addLast(filter.getClass().getName(), filter);
/*     */     }
/* 246 */     this.acceptor.getSessionConfig().setBothIdleTime(sc.getMaxIdleTime());
/* 247 */     this.acceptor.getSessionConfig().setWriteTimeout(sc.getWriteTimeout());
/* 248 */     this.acceptor.setHandler(new NioHandlerDispatcher(this));
/*     */     try {
/* 250 */       this.acceptor.bind();
/*     */     } catch (Throwable e) {
/* 252 */       Zimbra.halt(getName() + " failed to start", e);
/*     */     }
/* 254 */     getLog().info("Starting %s on %s", new Object[] { getName(), this.acceptor.getLocalAddress() });
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public void stop(int timeout)
/*     */   {
/* 265 */     getLog().info("Initiating shutdown");
/*     */     
/*     */ 
/*     */ 
/* 269 */     closeSessions();
/* 270 */     this.acceptor.unbind();
/* 271 */     ExecutorService executor = (ExecutorService)this.executorFilter.getExecutor();
/* 272 */     executor.shutdown();
/*     */     try {
/* 274 */       executor.awaitTermination(timeout, TimeUnit.SECONDS);
/*     */     }
/*     */     catch (InterruptedException ignore) {}
/* 277 */     executor.shutdownNow();
/*     */   }
/*     */   
/*     */   public void stop()
/*     */   {
/* 282 */     stop(getConfig().getShutdownTimeout());
/*     */   }
/*     */   
/*     */   private void closeSessions() {
/* 286 */     for (IoSession session : getSessions().values()) {
/* 287 */       getLog().info("Closing session = " + session);
/* 288 */       NioHandler handler = NioHandlerDispatcher.getHandler(session);
/* 289 */       if (handler != null) {
/*     */         try {
/* 291 */           handler.dropConnection();
/*     */         }
/*     */         catch (IOException ignore) {}
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public Map<Long, IoSession> getSessions() {
/* 299 */     return this.acceptor.getManagedSessions();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   protected abstract NioHandler createHandler(NioConnection paramNioConnection);
/*     */   
/*     */ 
/*     */ 
/*     */   protected abstract ProtocolCodecFactory getProtocolCodecFactory();
/*     */   
/*     */ 
/*     */   protected void registerMBean(String type)
/*     */   {
/* 313 */     MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
/*     */     try {
/* 315 */       mbs.registerMBean(new NioServerStats(this), new ObjectName("ZimbraCollaborationSuite:type=" + type));
/*     */     } catch (Exception e) {
/* 317 */       getLog().warn("Unable to register NioServerStats mbean", e);
/*     */     }
/*     */   }
/*     */   
/*     */   public Log getLog() {
/* 322 */     return getConfig().getLog();
/*     */   }
/*     */   
/*     */   private static final class DefaultEncoder extends ProtocolEncoderAdapter
/*     */   {
/*     */     public void encode(IoSession session, Object msg, ProtocolEncoderOutput out) {
/* 328 */       if ((msg instanceof IoBuffer)) {
/* 329 */         IoBuffer buf = (IoBuffer)msg;
/* 330 */         out.write(buf);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   protected int getNumConnections()
/*     */   {
/* 339 */     return this.acceptor.getManagedSessionCount();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   protected int getNumThreads()
/*     */   {
/* 346 */     Executor ex = this.executorFilter.getExecutor();
/* 347 */     if (!(ex instanceof ThreadPoolExecutor)) {
/* 348 */       ZimbraLog.perf.debug("Unexpected Executor type %s.  NioServer.getNumThreads() returning 0.", new Object[] { ex.getClass().getName() });
/*     */       
/* 350 */       return 0;
/*     */     }
/* 352 */     return ((ThreadPoolExecutor)ex).getPoolSize();
/*     */   }
/*     */   
/*     */   protected Set<String> getThrottleSafeHosts() throws ServiceException
/*     */   {
/* 357 */     Set<String> safeHosts = new HashSet();
/* 358 */     for (com.zimbra.cs.account.Server server : Provisioning.getInstance().getAllServers()) {
/* 359 */       safeHosts.add(server.getServiceHostname());
/*     */     }
/* 361 */     for (String ignoredHost : this.config.getThottleIgnoredHosts()) {
/* 362 */       safeHosts.add(ignoredHost);
/*     */     }
/* 364 */     return safeHosts;
/*     */   }
/*     */   
/*     */   protected Set<String> getThrottleWhitelist() throws ServiceException
/*     */   {
/* 369 */     Set<String> safeHosts = new HashSet();
/* 370 */     for (String whitelistHost : this.config.getThrottleWhitelist()) {
/* 371 */       safeHosts.add(whitelistHost);
/*     */     }
/* 373 */     return safeHosts;
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/server/NioServer.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */